<?php
/*
 *		Api.php
 *		public
 *		@param Get
 *						@@param string $url support for json/xml
 *						@@return array
 *		@param Set
 *						@@param array $data
 *						@@param string $type json/xml
 *						@@return string json/xml document
 *
 *		private
 *		@param $transform
 *		@param $FixResult
 *		@param FixApi
 *						@@param array $input
 *						@@param array $apimodel
 *						@@return  array FixApi
 *		@param FixList
 *						@@param array $input
 *						@@param array $itemmodel
 *						@@return array Fix Api List
 *		@param Search
 *						@@param array $input
 *						@@param string $searchkey
 *						@@param string $splitstr
 *						@@if $searchkey have $splitstr then Fix the $searchkey and $childkeys for $this->GetValue
 *		@param GetValue
 *						@@param array $input
 *						@@param string $searchkey
 *						@@Get the value array in $input where $key == $searchkey or {$searchkey=>$childkeys[0]=>$childkeys[1]......$childkeys[n]}'s value
 *		@param GetChildrenValue
 *						@@param string $key
 *						@@param array $val
 *						@@param string $searchkey
 *						@@param array $childkeys
 *		@param GetChildValue
 *						@@param array $arrdata
 *						@@param array $childkeys
 */
//error_reporting(E_ALL || ~E_NOTICE);
include_once(CLASS_PATH."Transform.php");
class Api{
	private $transform;
	private $cache;
	public function Api(){
		$this->transform	= new Transform();
		$this->cache		= array();
	}
	/**
	 * Get Api data.
	 * @param string $url support for json/xml
	 * @return array
	 */
	public function Get($url,$apimodel,$type,$cache = false){
		try {
			//print_r( $url);
			$apidata		= $this->resposecache($url,$type,$cache);
		} catch (Exception $e) {
		}
		//print_r($apidata);
		return $this->FixApi($apidata,$apimodel);
	}
	/**
	 * Set Api data.
	 * @param array $data
	 * @param string $type json/xml
	 * @return string json/xml document
	 */
	public function Set($data,$type="JSON"){
		$apidata		= NULL;
		if($type=="JSON"){
			$apidata	= $this->transform->ArrayToJson($data);
		}
		else{
			$apidata	= $this->transform->ArrayToXml($data);
		}
		try{
			$apidata	= preg_replace("#\\\u([0-9a-f]+)#e", "iconv('UCS-2BE', 'UTF-8', pack('H4', '\\1'))", $apidata);
		}catch (Exception $e) {}
		return $apidata;
	}
	/**
	 * Fix Api data to api model.
	 * @param array $input
	 * @param array $apimodel
	 * @return array Fix Api data
	 */
	private function FixApi($input,$apimodel){
		$result		= array("Error" =>"err api data");
		$Special	= false;
		if(is_array($input)&&is_array($apimodel)){
			$result = array();
			foreach($apimodel as $key=>$val){
				$Special = false;
				if(is_array($val)){
					$result[$key] = $this->FixList($input,$val);
				}else{//if not an array the $input has only one val
					////////////////////////////////////////////////
					//http://bidders.co.jp/aitem/|ItemNo
					//to
					//http://bidders.co.jp/aitem/142051864
					$front = NULL;
					if(strpos($val,"||")){
						$searchkeys	= explode("||", $val);
						$val		=checknull("1", $searchkeys);
						$front		= $this->GetAndCheckVal($input,checknull("0", $searchkeys));
						$Special	= true;
					}elseif(strpos($val,"|")){
						$searchkeys	= explode("|", $val);
						$val=checknull("1", $searchkeys);
						$front		= checknull("0", $searchkeys);
					}
					$result[$key]	= $front.$this->GetAndCheckVal($input,$val);
				}
			}
			if(!in_array("Available",	array_keys($result))){
				$result["postageFlag"] = $this->checkPostageFlag($result,$Special);
			}
		}
		return $result;
	}
	private function checkPostageFlag($apidata,$Special=false){
			$resultpostageflag	= checknull("postageFlag",	$apidata);
			$resulttitle		= checknull("title",		$apidata);
			if(preg_match("/送料無料/",$resulttitle,$m)){
          return "送料無料";
			}
			if(preg_match("/送料無料|\./",$resultpostageflag,$m)){
          if(preg_match("/条件付/",$resultpostageflag,$m1)){
              return "1";
          }
          return "送料無料";
			}
			if(empty($resultpostageflag)&&$Special){
				return "送料無料"; 
			}
			return "1";
	}
	private function GetAndCheckVal($input,$val){
		$key = $val;
		$arrdata = $this->Search($input,$val);
		if(is_array($arrdata)){$arrdata=checknull("0", $arrdata);}
		return empty($arrdata)?$this->KeepSiteValue($key,$val):$this->FixTime($key,$arrdata);
	}
	private function KeepSiteValue($key,$val){
		$value = "";
		if($key=="site"){
			$value = $val;
		}
		return $value;
	}
	private function FixTime($key,$val){
		if($key=="endtime"||$key=="starttime"||$key=="EndDate"){
			$val = str_replace(array("年","月","日"),array("/","/",""),$val);
			$val = date(DATE_ATOM,strtotime($val));
		}
		return $val;
	}
	/**
	 * Get Item Array
	 * @param array $input
	 * @param array $itemmodel
	 * @return array Item Array
	 */
	private function FixList($input,$itemmodel){
		$result = array();
		foreach($itemmodel as $key=>$val){
			$arrdata = $this->Search($input,$key);
			if(!empty($arrdata)){
				foreach($arrdata as $itemi=>$itemval){
					if(is_array($val)){
						$isDeleteflag = NULL;//00000000 result ==null
						$isDelete = NULL;
						foreach($val as $keyA=>$valA){
							$SelectVal = $this->Search($itemval,$valA);
							if(is_array($SelectVal)){$SelectVal=checknull("0", $SelectVal);}
							$result[$itemi][$keyA] = empty($SelectVal)?$this->KeepSiteValue($keyA,$valA):$this->FixTime($keyA,$SelectVal);
							if($keyA!="site"){
								$checkvalue = checknull($itemi, $result);
								$isDelete .= checknull($keyA, $checkvalue,"1");
								//$isDelete .= empty(checknull($keyA, checknull($itemi, $result)))?NULL:"1";
							}
						}
						if(is_null($isDelete)){$result[$itemi]=NULL;}
					}else{
						$result[$itemi] = $this->Search($itemval,$valA);
					}
				}
			}
		}
		return $result;
	}
	/**
	 * if $searchkey have $splitstr then Fix the $searchkey and $childkeys for $this->GetValue
	 * @param array $input
	 * @param array $searchkey
	 * @param string $splitstr
	 */
	private function Search($input,$searchkey,$splitstr = "=>"){
		//echo $searchkey."\n";
		$this->cache[$searchkey] = checknull($searchkey, $this->cache);
		if(empty($this->cache[$searchkey])||!is_array($this->cache[$searchkey])){
			$childkeys = array();
			if(strpos($searchkey, $splitstr)){
				$childkeys = explode($splitstr, $searchkey);
				$searchkey = checknull("0", $childkeys);
				array_shift($childkeys);
			}
			$this->cache[$searchkey] = $this->GetValue($input,$searchkey,$childkeys);
		}
		return $this->cache[$searchkey];//$this->GetValue($input,$searchkey,$childkeys);
	}
	/**
	 * Get the value array in $input where $key == $searchkey or {$searchkey=>$childkeys[0]=>$childkeys[1]......$childkeys[n]}'s value
	 * @param array $input
	 * @param array $searchkey
	 * @param array $childkeys
	 */
	private function GetValue($input,$searchkey,$childkeys = array()){
		$result = NULL;
		if(is_array($input)&&!empty($searchkey)){
			if (array_key_exists($searchkey,$input)){
				$result = checknull($searchkey, $input);
				if(count($childkeys)>0&&is_array($result)){
					$result = $this->GetChildrenValue($result,$childkeys);
				}
			}else{
				foreach($input as $key=>$val){
					if(empty($result)){
						$result = $this->GetValue($val,$searchkey,$childkeys);
						continue;
					}else{
						break;
					}
				}
			}
		}
		//echo $result."\n";
		return $result;
	}
	/**
	 * Get the value in $val[0] or $val[$childkeys[0]] where {$val=>$childkeys[0]=>$childkeys[1]......$childkeys[n]}'s value
	 * @param string $input
	 * @param array $childkeys
	 */
	private function GetChildrenValue($input,$childkeys){
		$result = array();
		$childkeys["0"] = checknull("0", $childkeys);
		if($childkeys["0"]=="{n}"){
			array_shift($childkeys);
			if (array_key_exists("0",$input)){
				foreach($input as $key=>$val){
					if(is_numeric($key)){
						array_push($result,$this->GetChildValue($val,$childkeys));
					}
				}
			}else{
				array_push($result,$this->GetChildValue($input,$childkeys));
			}
			//print_r($result);
		}else{
			array_push($result,$this->GetChildValue($input,$childkeys));
		}
		if(count($result)==0){$result=NULL;}
		return $result;
	}
	/**
	 * Get the value in $arrdata where {$arrdata=>$childkeys[0]=>$childkeys[1]......$childkeys[n]}'s value
	 * @param array $arrdata
	 * @param array $childkeys
	 */
	private function GetChildValue($input,$childkeys){
		foreach($childkeys as $skey=>$sval){
			$input = checknull($sval, $input);
		}
		if(empty($input))$input = NULL;
		return $input;
	}
	///////////////////////////////////////////////
	//curl で　api　ページ　を　取る
	//param $url apiurl
	private function getapi($url,$type){
		//$body = file_get_contents($url,FILE_USE_INCLUDE_PATH);
		$curl = new curl($url);
		$body = $curl->execute();
		//JSON to JSONP
		$pattern = NULL;
		$replacement = NULL;
		if($type=="JSONP"){//delete callback
			$pattern = "/(.[^\(]*)\({(.*)}\)/";
			$replacement = "{\$2}";
			$body = preg_replace($pattern, $replacement, $body);
			$type = "JSON";
		}
		//print_r($body);
		$apidata=NULL;
		if($type=="JSON"){$apidata = $this->transform->JsonToArray($body);}
		else{$apidata = $this->transform->XmlToArray($body);}

		return $apidata;
	}
	//キャッシュファイルを取得
	private function resposecache($url,$type,$cache = false){
		if($cache === false){return $this->getapi($url,$type); }
		$content        =   array();
		$isMakeCache    =   true;
		if(preg_match("/.*Signature/",$url,$urlmatch)){
			$cachFileName =  CACHE_PATH.md5(checknull("0", $urlmatch));
		}else{
			$cachFileName =  CACHE_PATH.md5($url);
		}
		if( file_exists( $cachFileName )){
			// 24時間以上経過してる？
			clearstatcache();
			$fTime  = @filemtime( $cachFileName );
			//$ckTiel  = strtotime( "-15minutes" );
			$ckTiel  = strtotime( "-".CACHE_TIME );
			if( $fTime && $fTime > $ckTiel ){
				// 1時間以内に作成されているので、使いまわします
				$isMakeCache  = false;
				$content      = unserialize( file_get_contents( $cachFileName ) );
			}
		}
		if(empty( $content)){
			$isMakeCache = true;
		}
		// キャッシュ再生成する？
		if( $isMakeCache ){
			$content = $this->getapi($url,$type);
			// 作成したデータをキャッシュしとく
			@file_put_contents( $cachFileName, serialize( $content) );
			@chmod( $cachFileName, 0666 );
		}
		// 返却
		return $content;
	}
	public function clean(){
		$this->cache = NULL;
	}
	public function __destruct(){
		unset($this->transform);
		unset($this->cache);
	}
}